using System.Diagnostics;
using FluentParser.Expressions;

namespace FluentParser.Expressions.Rules.Decoration
{
    /// <summary>
    /// Decorares an expression by transforming every source
    /// failures into success.
    /// </summary>
    /// <example><code>
    /// var sourceExpr = ParseString.Regex("[A-Za-z]+");
    /// var newExpr = sourceExpr.Optional("DefaultValue");
    /// 
    /// sourceExpr.Parse("SomeWord")   --> "SomeWord"
    /// sourceExpr.Parse("1234567890") --> failure!
    /// newExpr.Parse("SomeWord")      --> "SomeWord"
    /// newExpr.Parse("1234567890")    --> "DefaultValue"
    /// </code></example>
    [DebuggerDisplay("[OptionalExpressionRule Source={Source} Default={DefaultValue}]")]
    public class OptionalExpressionRule<TResult> : Expr<TResult> 
    {
        public Expr<TResult> Source { get; private set; }
        public TResult DefaultValue { get; private set; }

        public OptionalExpressionRule(Expr<TResult> source, TResult defaultValue)
        {
            Source = source;
            DefaultValue = defaultValue;
            TypeOperation = OperationType.Decoration;
        }

        public override ParsingResult<TResult> Parse(GrammarContext context, int index)
        {
            return Source.Parse(context, index) ??
                   new ParsingResult<TResult>(index, 0, default(TResult));
        }

        public override void ParseNode(GrammarContext context, ParsingNodeResult node)
        {
            ParsingNodeResult childNode = node.AddChild(Source, context);
            node.IsSuccess = true;
            node.Value = childNode.IsSuccess ? childNode.Value : default(TResult);
        }
    }
}